package com.katesoft.scale4j.agent.jmx;

import com.katesoft.scale4j.agent.ServiceLauncher;
import com.katesoft.scale4j.agent.service.ServiceDetails;
import com.katesoft.scale4j.agent.service.ServiceStatus;
import com.katesoft.scale4j.log.LogFactory;
import com.katesoft.scale4j.log.Logger;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;

import java.util.Date;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;

/**
 * Very simple exporter of agent functionality through JMX.
 *
 * @author kate2007
 */
@ManagedResource(objectName = IServiceManagerMBean.OBJ_NAME)
public class ServiceManagerJMXExporter implements IServiceManagerMBean
{
    private Logger logger = LogFactory.getLogger(getClass());
    private ServiceLauncher launcher;
    private ClassPathXmlApplicationContext context;

    public void setLauncher(ServiceLauncher launcher)
    {
        this.launcher = launcher;
    }

    //methods
    @Override
    @ManagedOperation
    public boolean isServiceRunning(String name)
    {
        ServiceDetails details = byName(name);
        return details.getStatus() == ServiceStatus.RUNNING;
    }

    @Override
    @ManagedOperation
    public String serviceStatus(String name)
    {
        ServiceDetails details = byName(name);
        return details.getStatus().name();
    }

    @Override
    @ManagedOperation
    public String serviceConfiguration(String name)
    {
        return byName(name).serviceConfiguration();
    }

    @Override
    @ManagedOperation
    public Date startedAt(String name)
    {
        ServiceDetails details = byName(name);
        return details.launchedAt();
    }

    @Override
    @ManagedOperation
    public String[] allServices()
    {
        ConcurrentMap<String, ServiceDetails> services = launcher.getServices();
        return services.keySet().toArray(new String[services.size()]);
    }

    @Override
    @ManagedOperation
    public String[] allServicesByStatus()
    {
        ConcurrentMap<String, ServiceDetails> services = launcher.getServices();
        String[] array = new String[services.size()];
        int i = 0;
        for (Entry<String, ServiceDetails> entry : services.entrySet()) {
            array[i++] = String.format("%s=%s", entry.getKey(), entry.getValue().getStatus().name());
        }
        return array;
    }

    @Override
    @ManagedOperation
    public void stopService(String name,
                            boolean forceKill) throws Exception
    {
        logger.info("calling jmx.stopService(%s,%s)", name, forceKill);
        byName(name);
        launcher.stopService(name, forceKill);
    }

    @Override
    @ManagedOperation
    public void stop(boolean forceKill)
    {
        logger.info("calling jmx.stop(%s)", forceKill);
        try {
            launcher.stopAllServices(forceKill);
            context.destroy();
        }
        catch (Exception e) {
            logger.error(e);
        }
        System.exit(-1);
    }

    @Override
    @ManagedOperation
    public void startService(String name)
    {
        logger.info("calling jmx.startService(%s)", name);
        byName(name);
        launcher.startService(name);
    }

    private ServiceDetails byName(String name)
    {
        ServiceDetails details = launcher.getServices().get(name);
        if (details == null) {throw new IllegalArgumentException(String.format("service %s not found", name));}
        return details;
    }

    public void setContext(ClassPathXmlApplicationContext context)
    {
        this.context = context;
    }
}
